package Boke2;

//利用环形队列实现我的阻塞队列
public class MyBlockingQueue {
    //初始化数组长度
    public int[]array=new int[100];
    //队列的头部
    public int head=0;
    //队列的尾部
    public int tail=0;
    //定义已有元素个数
    public  int size=0;

    public void put(int k) throws InterruptedException {
        //多线程环境下，这里的修改操作存在线程安全,所以对类对象进行加锁
        synchronized (this){
            //判断是否已满
            //用while而不用if的原因是在阻塞等待过程中，结果都是“千变万化”的
            //我们永远都不能肯定size== array.length这个条件是否在阻塞唤醒后
            //发生变化，所以最保险的做法是阻塞等待唤醒后再判断一次。
            while(size== array.length){
                //如果队列为满则先阻塞等待，直到不满时唤醒
                this.wait();
            }
            //给队尾赋值插入
            array[tail]=k;
            tail++;
            //判断tail是否到达数组尾部
            if(tail== array.length){
                tail=0;
            }
            //元素加1
            size++;
            //唤醒take中由于队列为空而造成的阻塞等待
            this.notify();
        }

    }

    public Integer take() throws InterruptedException {
        //多线程环境下，这里的修改操作存在线程安全,所以对类对象进行加锁
        synchronized (this){
            //判断是否为空
            while(size==0){
                //当队列为空时，进行阻塞等待，直到插入元素成功后唤醒
                this.wait();
            }
            //弹出队首元素
            int n=array[head];
            head++;
            if(head== array.length){
                head=0;
            }
            size--;
            //唤醒put中由于队列为满而造成的阻塞等待
            this.notify();
            return n;
        }
    }




    public static void main(String[] args) {
        //实例化一个阻塞队列
        MyBlockingQueue queue=new MyBlockingQueue();
        //创建线程t1进行生产
        Thread t1=new Thread(()->{
            int a=0;
            while (true){
                try {
                    queue.put(a);
                    System.out.println("t1生产："+a);
                    a++;
                    //降低生产速度
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
t1.start();
        //创建线程t2进行消费
        Thread t2=new Thread(()->{
            while (true){
                try {
                    int a= 0;
                    a = queue.take();
                    System.out.println("t2消费："+a);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
t2.start();

    }

}
